<template>
  <div class="calendar">
    <div class="calendar-top">
      <div class="monthChoice">
        <a-space style="justify-content: space-between; width: 100%">
          <div style="font-size: 20px">
            {{ showMonth.format('YYYY') }} | {{ showMonth.format('MM') }}月
          </div>
          <a-radio-group
            v-if="type === 1"
            :default-value="Number(showMonth.format('M'))"
            @change="(e) => showMonthChnage(e)"
          >
            <a-radio
              v-for="item in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]"
              :value="item"
              :key="item"
            >
              <template #radio="{ checked }">
                <div
                  class="year"
                  :class="{
                    'is-month': checked
                  }"
                >
                  {{ item }}月
                </div>
              </template>
            </a-radio>
          </a-radio-group>
          <div class="month" v-if="type === 2">
            <icon-left
              @click="showMonthChnage($event, 'last')"
              :style="{
                color: showMonth.format('M') === '1' ? '#cccccc' : '#fff',
                cursor: showMonth.format('M') === '1' ? 'no-drop' : 'pointer'
              }"
            />
            {{ showMonth.format('MM') }}月
            <icon-right
              @click="showMonthChnage($event, 'next')"
              :style="{
                color: showMonth.format('M') === '12' ? '#cccccc' : '#fff',
                cursor: showMonth.format('M') === '12' ? 'no-drop' : 'pointer'
              }"
            />
          </div>
          <a-space v-if="type === 3">
            <div
              class="week"
              :class="{ 'is-week': item === isWeek }"
              v-for="item in weekNum"
              :key="item"
              @click="showWeekChnage(item)"
            >
              第 {{ numStr[item - 1] }} 周
            </div>
          </a-space>
        </a-space>
      </div>
      <a-grid
        :cols="7"
        :colGap="0"
        :rowGap="0"
        style="border-top: 1px solid #e5e6eb"
      >
        <a-grid-item
          style="display: flex; justify-content: center; font-weight: 700"
          v-for="(item, index) in ['一', '二', '三', '四', '五', '六', '日']"
          class="weekName"
          :key="index"
        >
          周{{ item }}
        </a-grid-item>
      </a-grid>
    </div>
    <a-grid :cols="7" :colGap="0" :rowGap="0" class="grid">
      <a-grid-item
        class="grid-item"
        v-for="item in dayList.data"
        :key="item.millisecond"
        @click="isVisible(item)"
        :class="{
          lastMonth:
            item.Monthtype === 'lastMonth' || item.weekType === 'lastWeek',
          nextMonth:
            item.Monthtype === 'nextMonth' || item.weekType === 'nextWeek'
        }"
        :style="{
          background: item.dateJs.isSame(nowDate) ? '#f2f9ff' : '#fff',
          cursor:
            item.Monthtype === 'thisMonth' || item.weekType === 'thisWeek'
              ? 'pointer'
              : null
        }"
      >
        <div class="title">
          <div style="display: flex; justify-content: space-between">
            <div style="color: #dcdcdc">{{ item.perpetualCalendar }}</div>
            <div :class="{ today: item.dateJs.isSame(nowDate) }">
              {{ item.dateJs.date() }}
            </div>
          </div>
          <div
            class="remark"
            v-if="
              item.Monthtype === 'thisMonth' || item.weekType === 'thisWeek'
            "
          >
            <div
              class="duty"
              :style="{
                background: item.type === 1 ? '#40a9ff' : '#ff6363'
              }"
            >
              {{ item.type === 1 ? '班' : '休' }}
            </div>
            <div>
              {{ item.note }}
            </div>
          </div>
        </div>
      </a-grid-item>
    </a-grid>
  </div>
  <a-modal v-model:visible="visible" @ok="handleOk" @cancel="handleCancel">
    <template #title> 设置工作日历 </template>
    <a-form :model="form" autoLabelWidth label-align="right">
      <a-form-item label="是否上班" show-colon>
        <div class="type">
          <div :class="{ isCheck: form.type === 1 }" @click="form.type = 1">
            上班
          </div>
          <div :class="{ isCheck: form.type === 2 }" @click="form.type = 2">
            休息
          </div>
        </div>
      </a-form-item>
      <a-form-item label="备注" show-colon>
        <a-textarea
          v-model="form.note"
          placeholder="请输入备注信息"
          allow-clear
        />
      </a-form-item>
    </a-form>
  </a-modal>
</template>

<script setup lang="ts">
import {
  GetHoliday,
  GetPerpetualCalendar
} from '@/apis/attendance/base-setting/index';
import { cloneDeep } from 'lodash';
import Dayjs from 'dayjs';
// APPID：lq1telfvvzqkzsne
// APPSECRET： mQSrrryXQdl66kfG2iO44R21pTNXUwtm
const props = withDefaults(
  defineProps<{
    week?: any[];
    monthly?: any[];
    isSynchronization: 1 | 2;
    vacationType: 1 | 2;
    type: 1 | 2 | 3;
    specialSetting: any[];
  }>(),
  {}
);
const emit = defineEmits(['update:specialSetting']);

const visible = ref(false);
const form: any = reactive({});
let nowDate = ref(Dayjs().startOf('d'));
let showMonth = ref(nowDate.value);
let numStr = ['一', '二', '三', '四', '五'];
let perpetualCalendar = reactive([]);
const isWeek = ref();
const weekNum = ref();
const synchronizationData: any = reactive({});
let dayList = reactive<any>({ data: [] });
let perpetualCalendarData: any = reactive({ data: [] });

let showMonthChnage = (e: any, mode?: string) => {
  if (typeof e === 'number') {
    const number = showMonth.value.month() + 1 - e;
    showMonth.value = showMonth.value.subtract(number, 'M');
  } else {
    if (
      (showMonth.value.format('M') === '12' && mode === 'next') ||
      (showMonth.value.format('M') === '1' && mode === 'last')
    ) {
      return;
    }
    showMonth.value =
      mode === 'last'
        ? showMonth.value.subtract(1, 'M')
        : showMonth.value.add(1, 'M');
  }
  initList();
};

const isVisible = (item: any) => {
  if (item.Monthtype === 'thisMonth' || item.weekType === 'thisWeek') {
    visible.value = true;
    Object.assign(form, item);
  }
};

const handleOk = () => {
  const { type, note, dateJs } = form;
  const newData = cloneDeep(props.specialSetting);
  const index = newData.findIndex(
    ({ date }: any) => date === dateJs.format('YYYY-MM-DD')
  );
  if (index === -1) {
    newData.push({
      type,
      note,
      date: dateJs.format('YYYY-MM-DD')
    });
  } else {
    newData[index] = {
      type,
      note,
      date: dateJs.format('YYYY-MM-DD')
    };
  }
  emit('update:specialSetting', newData);
  handleCancel();
};

const handleCancel = () => {
  for (const key in form) {
    delete form[key];
  }
};

let showWeekChnage = (mode: number) => {
  const offset = mode - isWeek.value;
  let thisMonth = showMonth.value.month();
  let nextWeek = showMonth.value.add(offset, 'w');
  let nextWeekMonth = nextWeek.month();
  if (thisMonth === nextWeekMonth) {
    showMonth.value = nextWeek;
  } else if (thisMonth > nextWeekMonth) {
    showMonth.value = showMonth.value.startOf('M');
  } else {
    showMonth.value = showMonth.value.endOf('M').startOf('D');
  }
  isWeek.value = mode;
  showWeek();
};

const showWeek = () => {
  let monthStart = showMonth.value.startOf('M');
  let thisMonth = showMonth.value.month();
  let weekStart = showMonth.value.day()
    ? showMonth.value.startOf('week').add(1, 'd').date()
    : showMonth.value.add(-1, 'd').startOf('week').add(1, 'd').date();
  let weekMonth = showMonth.value.add(-1, 'd').startOf('week').month();
  let startNum =
    (monthStart.day() ? monthStart.day() - 1 : 6) +
    (thisMonth === weekMonth ? weekStart : 1) -
    1;
  for (let i = 0; i < startNum; i += 1) {
    dayList.data[i].weekType = 'lastWeek';
  }
  let centerNum = 7 - (thisMonth === weekMonth ? 0 : monthStart.day() - 1);
  for (let i = 0; i < centerNum; i += 1) {
    dayList.data[startNum + i].weekType = 'thisWeek';
  }
  for (let i = startNum + centerNum; i < dayList.data.length; i += 1) {
    dayList.data[i].weekType = 'nextWeek';
  }
};

const nowWeek = () => {
  const today = new Date(showMonth.value.format('YYYY-MM-DD'));
  const firstDayOfMonth = new Date(today.getFullYear(), today.getMonth(), 1);
  const dayOfWeek = (firstDayOfMonth.getDay() + 6) % 7; // 将星期天(0)转换为星期一(1)
  const dayOfMonth = today.getDate();
  const weekOfMonth = Math.ceil((dayOfMonth + dayOfWeek) / 7);
  const lastDayOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0);
  const daysInMonth = lastDayOfMonth.getDate();
  const daysInFirstWeek = 7 - dayOfWeek;
  const daysInRemainingWeeks = daysInMonth - daysInFirstWeek;
  const weeksInMonth = 1 + Math.ceil(daysInRemainingWeeks / 7);
  isWeek.value = weekOfMonth;
  weekNum.value = weeksInMonth;
};

const init = async () => {
  const res = await GetHoliday(showMonth.value.year());
  const res1 = await GetPerpetualCalendar({ year: showMonth.value.year() });
  Object.assign(perpetualCalendarData.data, res.data);
  Object.assign(perpetualCalendar, res1);
  perpetualCalendar.forEach((ele: any) => {
    synchronizationData[ele.date] = ele.typeDes;
  });
  initList();
};

const isPerpetualCalendar = (date: any) => {
  const month = date.month() + 1;
  const day = date.format('YYYY-MM-DD');
  let dayName = perpetualCalendarData.data
    .filter((ele: any) => ele.month === month)[0]
    ?.days.filter((ele: any) => ele.date === day)[0]?.lunarCalendar;
  return dayName;
};
init();

const initList = () => {
  let monthStart = showMonth.value.startOf('M');
  let monthEnd = showMonth.value.endOf('M').startOf('D');
  let list: any = [];
  let startNum = monthStart.day() ? monthStart.day() - 1 : 6;
  for (let i = 0; i < startNum; i += 1) {
    let dateJs = monthStart.subtract(i + 1, 'd');

    list.splice(0, 0, {
      dateJs,
      type: isType(
        dateJs,
        'lastMonth',
        props.isSynchronization === 1
          ? synchronizationData[dateJs.format('YYYY-MM-DD')]
          : ''
      ),
      millisecond: dateJs.valueOf(),
      Monthtype: 'lastMonth',
      perpetualCalendar: isPerpetualCalendar(dateJs),
      perpetualCalendarName:
        props.isSynchronization === 1
          ? synchronizationData[dateJs.format('YYYY-MM-DD')]
          : ''
    });
  }
  let centerNum = monthEnd.toDate().getDate();
  for (let i = 0; i < centerNum; i += 1) {
    let dateJs = monthStart.add(i, 'd');
    list.push({
      dateJs,
      type: isType(
        dateJs,
        'thisMonth',
        props.isSynchronization === 1
          ? synchronizationData[dateJs.format('YYYY-MM-DD')]
          : ''
      ),
      millisecond: dateJs.valueOf(),
      Monthtype: 'thisMonth',
      perpetualCalendar: isPerpetualCalendar(dateJs),
      perpetualCalendarName:
        props.isSynchronization === 1
          ? synchronizationData[dateJs.format('YYYY-MM-DD')]
          : '',
      note: props.specialSetting.filter(
        (ele) => ele.date === dateJs.format('YYYY-MM-DD')
      )[0]?.note
    });
  }
  let endNum = 7 - (monthEnd.day() || 7);
  for (let i = 0; i < endNum; i += 1) {
    let dateJs = monthEnd.add(i + 1, 'd');
    list.push({
      dateJs,
      type: isType(
        dateJs,
        'nextMonth',
        props.isSynchronization === 1
          ? synchronizationData[dateJs.format('YYYY-MM-DD')]
          : ''
      ),
      millisecond: dateJs.valueOf(),
      Monthtype: 'nextMonth',
      perpetualCalendar: isPerpetualCalendar(dateJs),
      perpetualCalendarName:
        props.isSynchronization === 1
          ? synchronizationData[dateJs.format('YYYY-MM-DD')]
          : ''
    });
  }
  dayList.data = list;
};

const isType = (dateJs: any, mode: string, perpetualCalendarName: string) => {
  //
  let specialSettingType = props.specialSetting.filter(
    (ele) => ele.date === dateJs.format('YYYY-MM-DD')
  )[0]?.type;
  if (specialSettingType) {
    return specialSettingType;
  } else if (perpetualCalendarName) {
    return 2;
  } else if (
    props.week &&
    Array.isArray(props.week) &&
    props.week.length !== 0 &&
    props.week.includes(dateJs.day())
  ) {
    return 2;
  } else if (
    mode === 'thisMonth' &&
    props.monthly &&
    Array.isArray(props.monthly) &&
    props.monthly.length !== 0 &&
    props.monthly.includes(dateJs.date())
  ) {
    return 2;
  } else {
    return 1;
  }

  //  ? 2 : 1;
};

watch(
  () => props.type,
  (val) => {
    initList();
    if (val === 3) {
      Object.assign(showMonth.value, nowDate.value);
      nowWeek();
      showWeekChnage(isWeek.value);
    }
  }
);

watch(
  () => props.week,
  () => {
    initList();
  }
);

watch(
  () => props.monthly,
  () => {
    initList();
  }
);

watch(
  () => props.isSynchronization,
  (val) => {
    if (val === 1) {
      perpetualCalendar.forEach((ele: any) => {
        dayList.data.forEach((item: any) => {
          if (ele.date === item.dateJs.format('YYYY-MM-DD')) {
            item.perpetualCalendarName = ele.typeDes;
          }
        });
      });
    } else {
      dayList.data.forEach((ele: any) => {
        ele.perpetualCalendarName = '';
      });
    }
    initList();
  }
);

watch(
  () => props.specialSetting,
  () => {
    initList();
  }
);

defineExpose({
  changeShowMonth: (date: Date) => {
    showMonth.value = Dayjs(date);
  }
});
</script>

<style lang="less" scoped>
.calendar {
  &-top {
    border-top: 1px var(--color-neutral-3) solid;
    border-left: 1px var(--color-neutral-3) solid;
    border-right: 1px var(--color-neutral-3) solid;
  }
  .monthChoice {
    // padding-left: 20px;
    padding: 10px 20px;
  }
  .weekName {
    padding: 15px;
    color: var(--color-neutral-8);
  }
  .grid {
    border-top: 1px var(--color-neutral-3) solid;
    border-left: 1px var(--color-neutral-3) solid;
    &-item {
      padding: 10px;
      height: 100px;
      border-bottom: 1px var(--color-neutral-3) solid;
      border-right: 1px var(--color-neutral-3) solid;

      .title {
        // display: flex;
        // justify-content: space-between;

        line-height: 24px;
        width: 100%;
        border-radius: 12px;
        text-align: center;
        margin-bottom: 10px;
      }
      .today {
        background: rgb(var(--arcoblue-6));
        color: #fff;
        border-radius: 50%;
        width: 25px;
        height: 25px;
      }
    }
    .lastMonth {
      background: #f5f5f5;
      color: var(--color-neutral-4);
    }

    .nextMonth {
      background: #f5f5f5;
      color: var(--color-neutral-4);
    }
  }
}
.year {
  width: 35px;
  height: 35px;
  text-align: center;
  line-height: 35px;
}
.is-month {
  border-radius: 50%;
  background: #85c8ff;
  color: #fff;
}
.month {
  // width: 150px;
  padding: 0 10px;
  margin-right: 20px;
  line-height: 35px;
  height: 35px;
  border-radius: 15px;
  background: #85c8ff;
  color: #fff;
  svg {
    cursor: pointer;
    margin: 0 5px;
  }
}
.week {
  padding: 0 10px;
  margin-right: 20px;
  line-height: 35px;
  height: 35px;
  cursor: pointer;
}
.is-week {
  border-radius: 15px;
  background: #85c8ff;
  color: #fff;
}
.remark {
  display: flex;
  justify-content: space-between;
  padding-top: 5px;
  .duty {
    width: 25px;
    height: 25px;
    border-radius: 50%;
    background: #40a9ff;
    color: #fff;
  }
}
.type {
  display: flex;
  border: 1px solid #e4e4e4;
  div {
    padding: 5px 10px;
    text-align: center;
    cursor: pointer;
  }
  div:nth-child(1) {
    border-right: 1px solid #e4e4e4;
  }
  .isCheck {
    background: #40a9ff;
    color: #fff;
  }
}
</style>
